package cn.appkf.flappybird.actor;

import com.alibaba.fastjson.JSONObject;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.maps.objects.PolylineMapObject;
import com.badlogic.gdx.scenes.scene2d.Actor;

import cn.appkf.flappybird.net.NetWorker;
import cn.appkf.flappybird.res.Res;
import cn.appkf.flappybird.stage.TestStage;
import cn.appkf.flappybird.ui.MyMap;

/**
 * Created by Administrator on 2016/7/28.
 */
public class MyActor extends Actor {


    public final static int STAY_LEFT = 0x01;
    public final static int STAY_RIGHT = 0x02;
    public final static int STAY_DOWN = 0x03;
    public final static int STAY_JUMP = 0x04;


    private float hpUp = 100;
    private float hp = 100;
    private float hpRe = 1;


    private String ID="";

    /**
     * 水平移动速度, px/s
     */
    private float moveVelocity = Res.Physics.MOVE_VELOCITY;

    /**
     * 小鸟竖直方向上的速度
     */
    private float velocityY;

    /**
     * 小鸟竖直方向上的重力加速度
     */
    private float gravity = Res.Physics.GRAVITY;


    private float mapX;
    private float mapY;


    private float face_offsetX = 10f;
    private float face_offsetY = 60f;
    private TextureRegion region;
    private TextureRegion stay_region;
    private TextureRegion face_region;

    private boolean isMoveLeft;
    private boolean isMoveRight;
    private boolean isMoveUp;
    private boolean isMoveDown;

    private boolean canMove = true;
    private boolean god = false;

    private int status = STAY_RIGHT;
    private int last_redirect = STAY_RIGHT;

    private int sync_state=0;

    MyMap map;
    private float stateTime;

    private boolean isOther=false;

    private Texture walkSheetTexture;
    private Texture walkSheetTexture2;
    // 行走动画
    private Animation walkAnimation;
    private Animation walkAnimation2;

    private TextureRegion currentFrame;

    private AssetManager manager;

    JSONObject jo;

    NetWorker netWorker;
    public MyActor(MyMap map, AssetManager manager, NetWorker netWorker) {

        this.netWorker=netWorker;

        this.manager=manager;

        jo=new JSONObject();
        this.stay_region = new TextureRegion(manager.get(TestStage.A_DOCIN,Texture.class));

        stateTime = 0;
        this.map = map;
        // 将演员的宽高设置为纹理区域的宽高（必须设置, 否则宽高默认都为 0, 绘制后看不到）
        //setSize(this.region.getRegionWidth(), this.region.getRegionHeight());

        // 也可以分开设置
        // setWidth(this.region.getRegionWidth());
        // setHeight(this.region.getRegionHeight());


        face_region = new TextureRegion(manager.get(TestStage.A_FACE1,Texture.class));

        walkSheetTexture = manager.get(TestStage.A_WALK_SEE,Texture.class);
        walkSheetTexture2 = manager.get(TestStage.A_WALK_SEE2,Texture.class);

        int frameRows = 5;  // 小人单元格的行数
        int frameCols = 5;  // 小人单元格的列数

        int perCellWidth = walkSheetTexture.getWidth() / frameCols;     // 计算每一个小人单元格的宽度
        int perCellHeight = walkSheetTexture.getHeight() / frameRows;   // 计算每一个小人单元格的高度

        setSize(perCellWidth, perCellHeight);
        // 按照指定的宽高作为一个单元格分割大图纹理, 分割后的结果为一个 5 * 6 的纹理区域二维数组, 数组中的元素是分割出来的小人单元格
        TextureRegion[][] cellRegions = TextureRegion.split(walkSheetTexture, perCellWidth, perCellHeight);
        TextureRegion[][] cellRegions2 = TextureRegion.split(walkSheetTexture2, perCellWidth, perCellHeight);

        // 把二维数组变为一维数组, 因为 Animation 只能接收一维数组作为关键帧序列, 数组中的一个元素（小人单元格的纹理区域）表示一个关键帧
        TextureRegion[] walkFrames = new TextureRegion[frameRows * frameCols];
        TextureRegion[] walkFrames2 = new TextureRegion[frameRows * frameCols];
        int index = 0;
        for (int row = 0; row < frameRows; row++) {
            for (int col = 0, col2 = frameCols - 1; col < frameCols; col++, col2--) {
                walkFrames[index] = cellRegions[row][col];
                walkFrames2[index] = cellRegions2[row][col2];
                index++;
            }
        }

        // 使用关键帧（纹理区域）数组 walkFrames 创建一个动画实例, 每一帧（一个小人单元格/纹理区域）播放 0.05 秒
        walkAnimation = new Animation(0.05F, walkFrames);
        walkAnimation2 = new Animation(0.05F, walkFrames2);

        /*
         * 设置播放模式:
         *
         * Animation.PlayMode.NORMAL: 正常播放一次（默认）
         * Animation.PlayMode.REVERSED: 倒序播放一次
         *
         * Animation.PlayMode.LOOP: 正常循环播放
         * Animation.PlayMode.LOOP_REVERSED: 倒序循环播放
         *
         * Animation.PlayMode.LOOP_RANDOM: 随机循环播放
         * Animation.PlayMode.LOOP_PINGPONG: 开关式（先正序再倒序）循环播放
         */
        walkAnimation.setPlayMode(Animation.PlayMode.LOOP);
        walkAnimation2.setPlayMode(Animation.PlayMode.LOOP);
    }


    public TextureRegion getRegion() {
        return region;
    }

    public void setRegion(TextureRegion region) {
        this.region = region;
        // 重新设置纹理区域后, 需要重新设置宽高
        setSize(this.region.getRegionWidth(), this.region.getRegionHeight());
    }


    @Override
    public void draw(Batch batch, float parentAlpha) {
        super.draw(batch, parentAlpha);

        // 如果 region 为 null 或者 演员不可见, 则直接不绘制
        if (region == null || !isVisible()) {
            return;
        }


        batch.draw(
                region,
                getX(), getY(),
                getOriginX(), getOriginY(),
                getWidth(), getHeight(),
                getScaleX(), getScaleY(),
                getRotation()
        );

        batch.draw(
                face_region,
                getX() + face_offsetX, getY() + face_offsetY,
                getOriginX(), getOriginY(),
                face_region.getRegionWidth(), face_region.getRegionHeight(),
                0.2f, 0.2f,
                getRotation()
        );


    }

    @Override
    public void act(float delta) {
        super.act(delta);

        if (this.hp != this.hpUp) {
            this.hp += this.hpRe * delta;
        }
        if (this.hp > this.hpUp) {
            this.hp = this.hpUp;
        }

        stateTime += delta;

        if (isMoveLeft) {
            if(!isOther&&sync_state!=STAY_LEFT){
                sync_state=STAY_LEFT;

                jo.put("type","move");
                jo.put("move",STAY_LEFT);
                netWorker.send(jo.toString());
            }
            last_redirect=STAY_LEFT;
            region = walkAnimation2.getKeyFrame(stateTime);
            float next_x=getMapX() - moveVelocity * delta;
            if (next_x > 0) {

            }else{
                next_x=0.1f;
            }
            setMapX(next_x);
        } else if (isMoveRight) {

            if(!isOther&&sync_state!=STAY_RIGHT){
                sync_state=STAY_RIGHT;

                jo.put("type","move");
                jo.put("move",STAY_RIGHT);
                netWorker.send(jo.toString());
            }

            last_redirect=STAY_RIGHT;
            region = walkAnimation.getKeyFrame(stateTime);

            float next_x=getMapX() + moveVelocity * delta;
            if (next_x < map.getMapWidth()) {

            }else{

                next_x=map.getMapWidth()-0.1f;
            }
            setMapX(next_x);
        } else {

            if(!isOther&&sync_state!=0){
                sync_state=0;
                jo.put("type","move");
                jo.put("move",0);
                netWorker.send(jo.toString());
            }
            region = stay_region;
        }


        // 递增位移


        checkMap(delta);

        if (this.status == STAY_JUMP) {
            region = stay_region;
        }


        if(isOther) {
            setX(mapX - map.getCam().position.x + map.getCam().viewportWidth / 2);
            setY(mapY - map.getCam().position.y + map.getCam().viewportHeight / 2);
        }

    }

    public void jump() {
//        gravity = Res.Physics.GRAVITY;
        this.status = STAY_JUMP;
        setVelocityY(Res.Physics.JUMP_VELOCITY);
    }

    public void heart(float h){
        this.hp-=h;
    }


    public Skill doSkill() {

        if(!isOther){
            jo.put("type","skill");
            netWorker.send(jo.toString());
        }
        Skill skill = new Skill(getMapX(), getMapY(),(TestStage) this.getStage(), map,this);
        return skill;
    }

    private void checkMap(float delta) {
        boolean did = false;
        this.velocityY += gravity * delta;
        float next_y = getMapY() + velocityY * delta;
        if (velocityY > 0) {
            did = false;
        } else {


            for (PolylineMapObject pmo : map.getDxs()) {
                did = checkDx(pmo, next_y);
                if (did) {
                    this.setVelocityY(0);
                    break;
                }
            }
        }
        if (!did) {
            setMapY(next_y);
            this.status = STAY_JUMP;
        } else {
            this.status = STAY_LEFT;
        }
    }

    private boolean checkDx(PolylineMapObject pmo, float next_y) {

        float last_x = -1;
        float last_y = -1;
        float now_x = 0;
        float now_y = 0;
        float should_y = 0;
        float[] ver = pmo.getPolyline().getVertices();
        boolean did = false;
        for (int i = 0; i < pmo.getPolyline().getVertices().length; i += 2) {

            now_x = pmo.getPolyline().getX() + ver[i];
            now_y = pmo.getPolyline().getY() + ver[i + 1];

            if (last_x == -1) {
            } else {

                if (getMapX() >= now_x && getMapX() <= last_x || getMapX() <= now_x && getMapX() >= last_x) {


                    if (now_y == last_y || now_x == last_x) {
                        should_y = last_y;
                    } else {
                        should_y = (now_y - last_y) / (now_x - last_x) * (getMapX() - last_x) + last_y;
                    }


                    if (next_y <= should_y && next_y >= should_y - 9) {
                        setMapY(should_y);
                        did = true;
                        break;
                    }
                }
            }
            last_x = now_x;
            last_y = now_y;
        }

        return did;
    }


    public String getID() {
        return ID;
    }

    public void setID(String ID) {
        this.jo.put("id",ID);
        this.ID = ID;
    }

    public int getLast_redirect() {
        return last_redirect;
    }

    public void setLast_redirect(int last_redirect) {
        this.last_redirect = last_redirect;
    }

    public boolean isMoveLeft() {
        return isMoveLeft;
    }

    public void setMoveLeft(boolean moveLeft) {
        isMoveLeft = moveLeft;
    }

    public boolean isMoveRight() {
        return isMoveRight;
    }

    public void setMoveRight(boolean moveRight) {
        isMoveRight = moveRight;
    }

    public boolean isMoveUp() {
        return isMoveUp;
    }

    public void setMoveUp(boolean moveUp) {
        isMoveUp = moveUp;
    }

    public boolean isMoveDown() {
        return isMoveDown;
    }

    public void setMoveDown(boolean moveDown) {
        isMoveDown = moveDown;
    }

    public boolean isOther() {
        return isOther;
    }

    public void setOther(boolean other) {
        isOther = other;
    }

    public float getVelocityY() {
        return velocityY;
    }

    public void setVelocityY(float velocityY) {
        this.velocityY = velocityY;
    }


    public float getMapX() {
        return mapX;
    }

    public void setMapX(float mapX) {
        this.mapX = mapX;
    }

    public float getMapY() {
        return mapY;
    }

    public void setMapY(float mapY) {
        this.mapY = mapY;
    }


    public float getHpUp() {
        return hpUp;
    }

    public void setHpUp(float hpUp) {
        this.hpUp = hpUp;
    }

    public float getHp() {
        return hp;
    }

    public void setHp(float hp) {
        this.hp = hp;
    }
}
